{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "48136d1b",
   "metadata": {},
   "source": [
    "# Week14_函数与模块"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1b4f0f0",
   "metadata": {},
   "source": [
    "--------\n",
    "* 记录人：liuqt    \n",
    "* 时间：2021-11-29   \n",
    "* week14   \n",
    "* 主要参考文档:\n",
    "> 1. [Python官方文档](https://python.org/doc)\n",
    "> 2. [博客--函数](https://www.cnblogs.com/xuzhichao/p/11570285.html)\n",
    "\n",
    "--------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a447ce1",
   "metadata": {},
   "source": [
    "## 本周学习目标\n",
    "> 1. 函数的定义\n",
    "> 2. 函数的使用\n",
    "> 3. 函数的参数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d61a067d",
   "metadata": {},
   "source": [
    "### 一、函数的定义\n",
    "* 定义一个函数的一般步骤"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1f990746",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0112358\n"
     ]
    }
   ],
   "source": [
    "a,b = 0,1\n",
    "while a <10:\n",
    "    print(a,end='')\n",
    "    a,b = b,a+b\n",
    "print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "951534e5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 1 2 3 5 8 13 21 34 \n"
     ]
    }
   ],
   "source": [
    "a, b = 0, 1\n",
    "while a < 50:\n",
    "    print(a, end=' ') # 0  1  1 2 ...\n",
    "    a, b = b, a+b # a = 1  a = 1  b = 2  a = 2 b = 3\n",
    "print()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d127f78f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# .....我想重复使用某一个功能（避免重复造轮子）\n",
    "#......使用的人可以不懂代码，只要会调用函数即可 function_name()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17c3b855",
   "metadata": {},
   "source": [
    "> 1. 定义函数的一般方法\n",
    "'''\n",
    "def function_name():  # 1. function_name 遵循变量定义的规则  区别数学函数==> f(x) python的函数可以自定义名称\n",
    "   \"\"\"函数的注释\"\"\"  # 2. 函数的注释可以和使用者交流\n",
    "   函数体         # 3. 函数体要和定义函数保持一定的tab缩进\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "491950f3",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fib(n):\n",
    "    \"\"\"Print a Fibonacci series up to n.\"\"\"\n",
    "    a,b = 0,1\n",
    "    while a < n:\n",
    "        print(a,end='')\n",
    "        a,b = b,a+b\n",
    "    print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "eceebef3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "01123581321345589\n"
     ]
    }
   ],
   "source": [
    "fib(100)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8643af42",
   "metadata": {},
   "outputs": [],
   "source": [
    "def hello():\n",
    "    \"\"\"打印你好，世界\"\"\"\n",
    "    print(\"hello world!\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "f6959c2f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "hello world!\n"
     ]
    }
   ],
   "source": [
    "hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5bd6b69e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 个人思考版本\n",
    "def hwn(user_name):\n",
    "    uesr_name = input(\"请输入你的用户名：\")\n",
    "    print(\"hello\",user_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "9d32e7cf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请输入你的用户名：liu\n",
      "hello liu\n"
     ]
    }
   ],
   "source": [
    "hwn(\"liu\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "84c18b6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 老师分享版本\n",
    "def hello(username):\n",
    "    print(\"你好，\"+username.title()+\"同学\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "5d90d478",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好，Liu同学\n"
     ]
    }
   ],
   "source": [
    "hello(\"liu\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2735297a",
   "metadata": {},
   "source": [
    "* 思考： 函数是否必须有 参数？\n",
    "* 注意：\n",
    "> 1. 在第一行定义函数中，不需要任何信息就能完成工作，因此括号是空的（即便如此，括号必不可少！）\n",
    "> 2. 要调用函数，可以依次指定函数名以及括号括起的必要信息。在第五行代码中，因为此函数hello()括号中不需要任何信息，只需要输入hello()即可。和预期效果一样，打印hello,world!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f410bf5e",
   "metadata": {},
   "source": [
    "### 3. 函数的参数\n",
    "> 1. 形式参数：\n",
    ">> 1. 定义参数时，写在function_name 括号里面的参数\n",
    ">> 2. 在定义函数时，形式参数不占用空间 \n",
    "> 2. 实际参数：\n",
    ">> 1. 调用函数时，写在function_name 括号里面的参数\n",
    ">> 2. 在使用函数时，形式参数 被 分配空间，变为实际参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "7d73d83d",
   "metadata": {},
   "outputs": [],
   "source": [
    "def describe_pet(animal_type,pet_name): # animal_type,pet_name 是形式参数 形参\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "3b3a1fbe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"dog\",\"豆豆\") # \"dog\",\"豆豆\" 实际参数 实参"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "a2b8e54b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a 豆豆.\n",
      "My 豆豆's name is Dog.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"豆豆\",\"dog\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e274fe3",
   "metadata": {},
   "source": [
    "* 当函数具有多个参数时\n",
    "\n",
    "> 1. 位置参数\n",
    ">> 1. 形式参数有先后顺序，函数调用过程中应考虑参数的先后顺序，避免出现顺序错误的笑话\n",
    ">> 2. 调用函数过程中要考虑形式参数的个数\n",
    "> 2. [关键字参数](Keyword Arguments)\n",
    ">> 1. 调用函数时，通过赋值的方式传递给定义好的形参变量数据\n",
    ">> 2. 关键字参数不考虑先后顺序，因为是指定变量赋值\n",
    "> 3. [默认参数](Default Argument Values)\n",
    ">> 1. 在形式参数中，提前预先设置一个用户可能使用的参数值\n",
    ">> 2. 用户在使用/调用函数时，可以省略不给默认参数赋值\n",
    ">> 3. 用户给默认参数赋值，将替换默认参数的值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "97f5d62c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def describe_pet(animal_type,pet_name): # animal_type,pet_name 是形式参数 形参\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "5992f3a8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "# 在使用 describe_pet() 函数时 需要考虑 参数的位置，从而进行参数数据的输入（实参的调用）\n",
    "# 位置参数：\n",
    "describe_pet(\"dog\",\"豆豆\") #　要根据　形式参数的位置先后顺序　先写animal_type，再写pet_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "f7e156d6",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "describe_pet() missing 2 required positional arguments: 'animal_type' and 'pet_name'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-14-f95e5f55e3d1>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mdescribe_pet\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: describe_pet() missing 2 required positional arguments: 'animal_type' and 'pet_name'"
     ]
    }
   ],
   "source": [
    "describe_pet()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "be99d5e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "# 关键字参数使用\n",
    "describe_pet(pet_name=\"豆豆\",animal_type=\"dog\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "0a6648e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 默认参数\n",
    "def describe_pet(pet_name,animal_type=\"dog\"): # animal_type,pet_name 是形式参数 形参\n",
    "    # 完善函数介绍\n",
    "    \"\"\"\n",
    "    显示宠物信息\n",
    "    \n",
    "    通过打印的方式显示宠物类型和宠物名称\n",
    "    参数信息：\n",
    "    pet_name： 是一个字符串，宠物名称\n",
    "    animal_type：是一个字符串，宠物类型\n",
    "    \"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "193b99a7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 豆豆.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"豆豆\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "fd4de23c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a 豆豆.\n",
      "My豆豆's name isCat.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"豆豆\",\"cat\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "77044f4f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function describe_pet in module __main__:\n",
      "\n",
      "describe_pet(animal_type, pet_name)\n",
      "    显示宠物信息\n",
      "    \n",
      "    通过打印的方式显示宠物类型和宠物名称\n",
      "    参数信息：\n",
      "    pet_name: 是一个字符串，宠物名称\n",
      "    animal_type:是一个字符串，宠物类型\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(describe_pet)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "218ac71b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "f947a808",
   "metadata": {},
   "source": [
    "------\n",
    "* 参数使用过程中的思考与问题：\n",
    "> 1. 思考：关键字参数(调用函数) 和 位置参数（调用函数） 是否可以一起使用？（可以）\n",
    ">> 1. positional argument follows keyword argument(位置参数<font style = \"color:red\">均</font>要放在关键字参数后面)\n",
    ">> 2. test1() got multiple values for argument 'x'(映射，不能出现 multiple values(多重值))\n",
    "> 2. 定义函数：默认参数（定义函数）和非默认参数（定义函数）的先后关系\n",
    ">> 1. non-default argument follows default argument(非默认参数<font style = \"color:red\">均</font>要放在默认字参数后面)\n",
    "------\n",
    "* 以下为测试代码："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "96e7205d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 案例1:\n",
    "def test1(x,y,z):\n",
    "    '''打印x，y，z的值'''\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "f9272483",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "# 在这里 2 是这里的关键字参数 对应 x，而y=3 是这里的位置参数\n",
    "test1(2,y=3,z=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "b6dd70dd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "test1(2,3,z=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "a9301b6f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "test1(2,z=4,y=3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "f76b08fe",
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "test1() got multiple values for argument 'x'",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-34-4a667719b3dd>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mtest1\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mx\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m3\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m5\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mTypeError\u001b[0m: test1() got multiple values for argument 'x'"
     ]
    }
   ],
   "source": [
    "test1(2,x=3,y=5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "ed48e8ed",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "non-default argument follows default argument (<ipython-input-39-ab06b5527fba>, line 2)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;36m  File \u001b[1;32m\"<ipython-input-39-ab06b5527fba>\"\u001b[1;36m, line \u001b[1;32m2\u001b[0m\n\u001b[1;33m    def test1(x,y=3,z):\u001b[0m\n\u001b[1;37m              ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m non-default argument follows default argument\n"
     ]
    }
   ],
   "source": [
    "# 案例2:\n",
    "def test1(x,y=3,z):\n",
    "    '''打印x，y，z的值'''\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "41d9b7eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 案例2:\n",
    "def test1(x,z,y=3):\n",
    "    '''打印x，y，z的值'''\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b5bb2a19",
   "metadata": {},
   "source": [
    "### 4.课本练习实践\n",
    "\n",
    "> 1. 请大家总结函数的优势\n",
    "> 2. 预习课本第四章函数与模块\n",
    ">> 1. 完成课本元音字母实践\n",
    ">> 2. 浏览模块，创建模块和调用模块，了解 PEP8 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "fe35cef0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def search4vowels(word):\n",
    "    '''\n",
    "    判断输入文本出现的元音字母有哪些\n",
    "    '''\n",
    "    vowels = set(\"aeiou\")\n",
    "    word = set(word)\n",
    "    print(vowels.intersection(word))\n",
    "#     print(vowess & word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "2a6fec35",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'o', 'e'}\n"
     ]
    }
   ],
   "source": [
    "search4vowels(\"hello world\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "240566d0",
   "metadata": {},
   "source": [
    "#  2.下周预告\n",
    "## 2.1函数返回值\n",
    "## 2.2模块介绍"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0683e3dc",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
